package com.mida.app.report.process.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.mida.app.report.enumData.DetailCode;
import com.mida.app.report.enumData.ReportProcessStatus;
import com.mida.app.report.enumData.ReportType;
import com.mida.app.report.innerdto.ReportFlowInfo;
import com.mida.app.report.process.DocReportListProcess;
import com.mida.app.report.service.*;
import com.mida.app.report.utils.MockTool;
import com.mida.app.report.utils.ReportListUtil;
import com.mida.app.report.utils.WatchUtil;
import com.mida.app.report.vo.*;
import com.mida.app.report.vo.request.PatientPageInfoVo;
import com.mida.app.report.vo.request.reqeustform.RegistrationListRequest;
import com.mida.bms.report.api.DocReportServiceApi;
import com.mida.bms.report.entity.DocReportServiceLock;
import com.mida.bms.report.vo.DocReportRequisitionRelationVo;
import com.mida.bms.report.vo.ReportSearchRequest;
import com.mida.bms.report.vo.ReportSearchVo;
import com.mida.bms.requestform.dto.RequestPageInfoDto;
import com.mida.bms.requestform.dto.ServiceInstanceInfoDto;
import com.mida.bms.requestform.request.RequestFormInfo;
import com.mida.dms.mdm.dto.ParameterDto;
import com.mida.dms.mdm.dto.UserDto;
import com.mida.dms.mdm.pojo.auto.MsdParameterValue;
import com.mida.tool.common.result.ListResult;
import com.mida.tool.common.ret.RespBody;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.StopWatch;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;


@Service
@Slf4j
@Transactional
public class DocReportListProcessImpl extends BaseProcess implements DocReportListProcess {


    @Value("${action.doc}")
    private boolean actionDoc;

    //登记单，检查单测试数据
    @Value("${combined.doc}")
    private boolean combined;

    @Value("${parameter.doc}")
    private Long parameter;

    @Autowired
    private MdmService mdmService;

    @Autowired
    private DocReportServiceApi docReportServiceApi;

    @Autowired
    private DetailCodingSystemService detailCodingSystemService;

    @Autowired
    private RequestService requestService;

    @Autowired
    private RequestFormService requestFormServiceImpl;

    @Autowired
    private RequestFormUtilSvc requestFormUtilSvcImpl;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    @Autowired
    private CacheService cacheService;


    @Autowired
    private DocReportServiceLockService docReportServiceLockService;

    /**
     * 1、申请单分页查询报告List
     *
     * @param vo
     * @return
     */
    @Override
    public ListResult<PageResultVo<DocReportListVo>> findPage(DocReportListPageVo vo, Long parameterValueSoid) throws Exception {
        log.info("开始分页查询报告list: " + vo.toString());
        StopWatch stopWatch = StopWatch.createStarted();
        ListResult result = new ListResult();
        PageResultVo pvo = new PageResultVo();
        Page page = new Page(vo.getCurrentPage(), vo.getPageSize());
        PageVo pageVo = new PageVo();
        List<DocReportListVo> list = new ArrayList<>();
        UserDto user = gainUserPart();
        // FIXME: yutao 2021/8/5  change to MAssert
        // XXX: yutao 2021/8/5 choose and return here. "if" must not have too many lines
        if (user == null) {
            pvo.setList(list);
            buildListSuccess(result, pvo);
            stopWatch.stop();
            log.info("本次查询时:" + stopWatch.getTime() + "ms. user为空");
            return result;
        }
        if (actionDoc == false) {
            //测试数据
            list = ReportListUtil.fillTestPvo(pvo, page, pageVo, list);
        } else {
            //初始化申请单查询条件
            RequestFormInfo requestFormInfo = ReportListUtil.initializeQueryConditionsToRequest(vo);
            //从申请单中查找待书写list
            list = findReportList(requestFormInfo, pvo, pageVo, list);
        }
        //补充报告类型
        list.forEach(m -> m.setReportType(parameterValueSoid));
        //补充报告信息
        list = gainReportMessage(list);
        //合单，并给第一条的list添加elements表示后面还有几个元素
        list = ReportListUtil.mergeRequest(list);
        pvo.setList(list);
        buildListSuccess(result, pvo);
        stopWatch.stop();
        log.info("本次查询耗时:" + stopWatch.getTime() + "ms");
        return result;
    }

    /**
     * 2、以检查号为维度的分页查询报告List
     *
     * @param vo
     * @return
     */
    @Override
    public ListResult<PageResultVo<DocReportListVo>> findPageWithCallingNo(DocReportListPageVo vo) throws IOException, ClassNotFoundException, CloneNotSupportedException, ExecutionException, InterruptedException {
        ListResult result = new ListResult();
        PageResultVo pvo = new PageResultVo();
        Page page = new Page(vo.getCurrentPage(), vo.getPageSize());

        //PageResultVo所需的pageVo和List<DocReportListVo> list
        PageVo pageVo = new PageVo();
        List<DocReportListVo> list = new ArrayList<>();
        UserDto user = gainUserPart();
        //测试数据
        if (combined == false) {
            //测试数据
            list = ReportListUtil.fillTestPvo(pvo, page, pageVo, list);

        } else {
            //初始化申请单查询条件
            RequestFormInfo requestFormInfo = ReportListUtil.initializeQueryConditionsToRequest(vo);
            //从申请单中查找待书写list
            list = findReportList(requestFormInfo, pvo, pageVo, list);

        }
        //补充报告状态和书写医生
        gainReportMessage(list);
        //合单，并给第一条的list添加elements表示后面还有几个元素
        list = ReportListUtil.examMergeRequest(list);
        pvo.setList(list);
        buildListSuccess(result, pvo);
        return result;
    }

    /**
     * 3、以登记号为维度的分页查询报告List
     *
     * @param vo
     * @return
     */
    @Override
    public ListResult<PageResultVo<DocReportListVo>> findPageWithRegisterNo(DocReportListPageVo vo) throws IOException, ClassNotFoundException, CloneNotSupportedException, ExecutionException, InterruptedException {
        ListResult result = new ListResult();
        PageResultVo pvo = new PageResultVo();
        Page page = new Page(vo.getCurrentPage(), vo.getPageSize());

        //PageResultVo所需的pageVo和List<DocReportListVo> list
        PageVo pageVo = new PageVo();
        List<DocReportListVo> list = new ArrayList<>();

        UserDto user = gainUserPart();

        if (combined == false) {//测试数据

            //从申请单中查找待书写list
            list = MockTool.RegisterData(page, list);

            ReportListUtil.initPageInfo(pvo, pageVo, 1L, 10L, 1L, ReportType.WRITE_REPORT_REGISTRATIONNO.code);
        } else {
            //初始化申请单查询条件
            RequestFormInfo requestFormInfo = ReportListUtil.initializeQueryConditionsToRequest(vo);
            //以登记标识为分页
            list = findReportList(requestFormInfo, pvo, pageVo, list);
            //登记号合单
        }
        //补充报告状态和书写医生
        gainReportMessage(list);
        //登记号合单
        ReportListUtil.registerMergeRequest(list);
        pvo.setList(list);
        buildListSuccess(result, pvo);
        return result;
    }

    /**
     * 4、根据参数的不同调用登记号，检查号，申请单号接口
     *
     * @param
     * @return
     */
    @Override
    public ListResult<PageResultVo<DocReportListVo>> transferInterfaceByParameter(DocReportListPageVo vo) throws Exception {
        ListResult result = new ListResult();
        UserDto user = gainUserPart();
        Long hospitalSoid = user.getHospitalSoid();
        //找到报告类型
        ListResult<ParameterDto> parameterByOrgInfoSoid = mdmService.findParameterByOrgInfoSoid(ReportType.REPORT_PARAMETERS_SOID.code, hospitalSoid,
                ReportType.WRITE_REPORT_RESOURCE_INFO_SOID.code);

        Long parameterValueSoid = null;
        if (ObjectUtils.isNotEmpty(parameterByOrgInfoSoid)) {
            ParameterDto parameterDto = parameterByOrgInfoSoid.getData();
            if (ObjectUtils.isNotEmpty(parameterDto)) {
                List<MsdParameterValue> parameterValueList = parameterDto.getParameterValueList();
                if (!CollectionUtils.isEmpty(parameterValueList)) {
                    parameterValueSoid = parameterValueList.get(0).getParameterValueSoid();
                }
            }
        }

        //根据报告的不同类型调用不同的接口
        if (ReportType.WRITE_REPORT_REQUEST.code.equals(parameterValueSoid)) {
            //1、申请单分页查询报告List
            ListResult<PageResultVo<DocReportListVo>> page = this.findPage(vo, parameterValueSoid);
            return page;
        } else if (ReportType.WRITE_REPORT_EXAMINATIONVISITSOID.code.equals(parameterValueSoid)) {
            //2、以检查号为维度的分页查询报告List
            ListResult<PageResultVo<DocReportListVo>> pageWithCallingNo = this.findPageWithCallingNo(vo);
            return pageWithCallingNo;
        } else if (ReportType.WRITE_REPORT_REGISTRATIONNO.code.equals(parameterValueSoid)) {
            //3、以登记号为维度的分页查询报告List
            ListResult<PageResultVo<DocReportListVo>> pageWithRegisterNo = this.findPageWithRegisterNo(vo);
            return pageWithRegisterNo;
        }

        buildBadRequestListWarn(result, "没有匹配的报告类型参数");
        return result;
    }


    /**
     * 获取申请单分页数据并封装成报告所需数据结构
     *
     * @param pvo
     * @param pageVo
     * @param list
     * @param request
     * @return
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @Override
    public List<DocReportListVo> getReportListWithReqeustFormInfo(PageResultVo pvo, PageVo pageVo, List<DocReportListVo> list, RegistrationListRequest request) throws ExecutionException, InterruptedException {
        Map<String, StopWatch> stopWatchMap = WatchUtil.createWatchs("requestFormServiceImpl.getRequestFormPage");
//        com.baomidou.mybatisplus.extension.plugins.pagination.Page<RegistrationListCompleteInfoVo> pages = requestFormServiceImpl.queryAllRequestFormPageInfo(request);
        stopWatchMap.get("requestFormServiceImpl.getRequestFormPage").start();
        RespBody<com.baomidou.mybatisplus.extension.plugins.pagination.Page<RequestPageInfoDto>> pages = requestFormServiceImpl.getRequestFormPage(request);
        stopWatchMap.get("requestFormServiceImpl.getRequestFormPage").stop();
        if (ObjectUtil.isNotEmpty(pages.getData()) && ObjectUtil.isNotEmpty(pages.getData().getRecords())) {
            DocReportListVo docReportListVo;
            List<RequestPageInfoDto> listTmp = pages.getData().getRecords();
            //批量查询患者信息并封装成map
            CompletableFuture<Map<BigDecimal, PatientPageInfoVo>> futurePatientInfoVosToMap =
                    CompletableFuture.supplyAsync(() -> requestFormUtilSvcImpl.queryPatientInfoVosToMap(pages.getData().getRecords()), threadPoolExecutor);
            //批量获取检查服务实例信息并封装成map
            CompletableFuture<Map<BigDecimal, List<ServiceInstanceInfoDto>>> futureServiceInstancesToMap =
                    CompletableFuture.supplyAsync(() -> requestFormUtilSvcImpl.changeServiceInstancesToMap(pages.getData().getRecords()), threadPoolExecutor);
            CompletableFuture.allOf(futurePatientInfoVosToMap, futureServiceInstancesToMap).join();
            Map<BigDecimal, List<ServiceInstanceInfoDto>> serviceInstanceMap = futureServiceInstancesToMap.get();
            Map<BigDecimal, PatientPageInfoVo> personDetailInfosMap = futurePatientInfoVosToMap.get();
            //批量查询检查服务实例信息并封装成map
            //获取需要批量查询的soid
            //注意区分索引
            List<HashSet<BigDecimal>> soidsSets = requestFormUtilSvcImpl.changeSoidsMapToSets(serviceInstanceMap);
            //todo 查询登记单信息 改成批量
            //索引0-msdServiceInstanceSoids
            //索引1-businessUnitSoids
            //索引2-dataSetSoids
            Set<BigDecimal> vistScenceCodeSet = listTmp.stream()
                    .map(RequestPageInfoDto::getVisitScenceCode)
                    .filter(ObjectUtil::isNotEmpty)
                    .collect(Collectors.toSet()
                    );

            Set<BigDecimal> emergencySignSet = listTmp.stream()
                    .map(RequestPageInfoDto::getEmergencySign)
                    .filter(ObjectUtil::isNotEmpty)
                    .map(BigDecimal::new)
                    .collect(Collectors.toSet()
                    );

            Set<BigDecimal> clinicCardTypeSet = listTmp.stream()
                    .map(RequestPageInfoDto::getClinicCardType)
                    .filter(ObjectUtil::isNotEmpty)
                    .map(BigDecimal::new)
                    .collect(Collectors.toSet()
                    );

            Set<BigDecimal> requestStatusSet = listTmp.stream()
                    .map(RequestPageInfoDto::getRequestStatus)
                    .filter(ObjectUtil::isNotEmpty)
                    .map(BigDecimal::new)
                    .collect(Collectors.toSet()
                    );

            soidsSets.get(2).addAll(vistScenceCodeSet);
            soidsSets.get(2).addAll(emergencySignSet);
            soidsSets.get(2).addAll(clinicCardTypeSet);
            soidsSets.get(2).addAll(requestStatusSet);
            //批量查询业务单元名称
            CompletableFuture<Map<BigDecimal, String>> futureBusinessNameSetToMap =
                    CompletableFuture.supplyAsync(() -> requestFormUtilSvcImpl.changeBusinessNameSetToMap(soidsSets.get(1)), threadPoolExecutor);

            //批量查询soid对应中文名
            CompletableFuture<Map<BigDecimal, String>> futureDataSetSoidNameSetToMap =
                    CompletableFuture.supplyAsync(() -> requestFormUtilSvcImpl.changeDataSetSoidNameSetToMap(soidsSets.get(2)), threadPoolExecutor);

            //批量获取登记单信息及其检查单信息并封装成map
            CompletableFuture<HashMap<BigDecimal, List<ApntRegistrationForm>>> futureRequestSoidApntRegistrationFormsMap =
                    CompletableFuture.supplyAsync(() -> requestService.getRequestSoidApntRegistrationFormsMap(new ArrayList<>(serviceInstanceMap.keySet())), threadPoolExecutor);
            CompletableFuture.allOf(futurePatientInfoVosToMap, futureServiceInstancesToMap).join();
            HashMap<BigDecimal, List<ApntRegistrationForm>> apntRegistrationFormsMap = futureRequestSoidApntRegistrationFormsMap.get();

            Map<BigDecimal, String> businessNameMap = futureBusinessNameSetToMap.get();
            Map<BigDecimal, String> dataSetSoidNameMap = futureDataSetSoidNameSetToMap.get();
            //索引3-requestDoctorSoids

            ReportListUtil.conventRequestFormToReport(list, listTmp, personDetailInfosMap, serviceInstanceMap, apntRegistrationFormsMap, businessNameMap, dataSetSoidNameMap);
            ReportListUtil.initPageInfo(pvo, pageVo, pages.getData().getCurrent(), pages.getData().getPages(), pages.getData().getTotal());
        }
        return list;
    }


    /**
     * @return void
     * @Author WXL
     * @Description 获取报告list
     * @Date 2021/8/7
     * @Param [vo, pvo, pageVo, list]
     **/
    private List<DocReportListVo> findReportList(RequestFormInfo requestFormInfo, PageResultVo pvo, PageVo pageVo, List<DocReportListVo> list) throws ExecutionException, InterruptedException {
        //优化前
//        queryReportList(pvo, pageVo, list, requestFormInfo);
        //优化后的
        RegistrationListRequest registrationListRequest = BeanUtil.copyProperties(requestFormInfo, RegistrationListRequest.class);

        return getReportListWithReqeustFormInfo(pvo, pageVo, list, registrationListRequest);

    }

    /**
     * @return void
     * @Author WXL
     * @Description 报告list返回对象中添加报告状态，医生
     * @Date 2021/8/7
     * @Param [list, employeeMap, relationMap]
     **/
    public List<DocReportListVo> addParametersToReport(DetailCodingSystemService detailCodingSystemService, List<DocReportListVo> list, Map<Long, String> employeeMap, Map<String, DocReportRequisitionRelationVo> relationMap) {
        //报告流程状态 map
        Map<Long, String> reportProcessStatusMap = detailCodingSystemService
                .getDataSetMapByDetailCode(DetailCode.REPORT_PROCESS_STATUS_CODE.code, null, false);
        //报告自身状态Map
        Map<Long, String> reportStatusMap = detailCodingSystemService
                .getDataSetMapByDetailCode(DetailCode.REPORT_STATUS.code, null, false);

        Map<Long, String> finalEmployeeMap = employeeMap;
        list.forEach(m -> {
            //补充返回vo中流转状态
            if (m.getRequestSoid() != null) {
                DocReportRequisitionRelationVo docReportRequisitionRelationVo = relationMap.get(String.valueOf(m.getRequestSoid()));
                if (ObjectUtils.isNotEmpty(docReportRequisitionRelationVo)) {
                    //1、报告流程状态
                    Long reportProcessStatus = docReportRequisitionRelationVo.getReportProcessStatus();
                    if (ObjectUtils.isNotEmpty(reportProcessStatus)) {//报告流程状态
                        m.setReportProcessStatus(reportProcessStatus);//设置报告状态soid
                        m.setReportStatus(reportProcessStatusMap.get(reportProcessStatus));//报告流转状态名称
                    }
                    //2、报告自身状态
                    Long status = docReportRequisitionRelationVo.getStatus();
                    if (ObjectUtils.isNotEmpty(status)) {
                        m.setStatus(status);
                        m.setStatusName(reportStatusMap.get(status));//报告自身状态名称
                    }
                    //3、设置报告soid
                    m.setStReportSoid(docReportRequisitionRelationVo.getStReportSoid());


                    Long firstWriteDoctor = docReportRequisitionRelationVo.getFirstWriteDoctor();//(书写医生)
                    Long firstTrialDoctor = docReportRequisitionRelationVo.getFirstTrialDoctor();//审核医生

                    if (ObjectUtils.isNotEmpty(finalEmployeeMap)) {
                        //(书写医生)
                        if (ObjectUtils.isNotEmpty(firstWriteDoctor)) {
                            m.setWritingDoctor(finalEmployeeMap.get(firstWriteDoctor));
                            m.setWritingDoctorSoid(firstWriteDoctor);

                        }
                        //审核医生
                        if (ObjectUtils.isNotEmpty(firstTrialDoctor)) {
                            m.setCheckDoctor(finalEmployeeMap.get(firstTrialDoctor));
                            m.setCheckDoctorSoid(firstTrialDoctor);
                        }

                    }
                } else {
                    m.setReportProcessStatus(ReportProcessStatus.TO_BE_WRITTEN.code);//设置报告状态soid
                    m.setReportStatus("待书写");//报告状态名称
                }

                // XXX: yutao 2021/8/8 在这里加上缓存，意义不大，但不加的话，有/无缓存间切换时会有问题
                ReportFlowInfo reportFlowInfo = new ReportFlowInfo();
                BeanUtils.copyProperties(m, reportFlowInfo);
                reportFlowInfo.setReportSoid(m.getStReportSoid());
                cacheService.cacheReportFlowInfo(reportFlowInfo);
            }
        });

        return list;
    }

    /**
     * 补充报告状态和书写医生
     *
     * @param list
     */
    private List<DocReportListVo> gainReportMessage(List<DocReportListVo> list) throws ExecutionException, InterruptedException {


        log.info("补充报告状态和书写医生begin: " + "==================================================");
        StopWatch stopWatch = StopWatch.createStarted();

        //先读缓存
        List<DocReportListVo> tmpList = new ArrayList<>();
        List<DocReportListVo> removList = new ArrayList<>();
        tmpList.addAll(list);
//        if (cacheService.enabled()) {
//            for (DocReportListVo dv : list) {
//                if (cacheService.exist(dv.getRequestSoid())) {
//                    cacheService.fillStatus(dv);
//                    removList.add(dv);
//                }
//            }
//        }
        tmpList.removeAll(removList);

        if (tmpList.size() == 0) {//都缓存则不用读数据库
            stopWatch.stop();
            log.info("补充报告状态和书写医生end: " + "==================================================" + "本次耗时:" + stopWatch.getTime() + "ms");
            return list;
        }
        StopWatch stopWatch2 = StopWatch.createStarted();

        //批量获取报告锁
        CompletableFuture<List<DocReportServiceLock>> docReportServiceLocksFuture =
                CompletableFuture.supplyAsync(
                        () -> docReportServiceLockService.selectLockList(tmpList), threadPoolExecutor);
        List<DocReportServiceLock> docReportServiceLocks = docReportServiceLocksFuture.get();

        //批量获取 报告状态，审核，书写医生、审核医生
        CompletableFuture<List<DocReportRequisitionRelationVo>> docReportRequisitionRelationVoListFuture =
                CompletableFuture.supplyAsync(
                        () -> queryDocReportRequisitionRelationVos(tmpList), threadPoolExecutor);
        List<DocReportRequisitionRelationVo> docReportRequisitionRelationVoList = docReportRequisitionRelationVoListFuture.get();
        stopWatch2.stop();
        log.info("docReportRequisitionRelationVoListFuture: " + "==================================================" + "本次耗时:" + stopWatch2.getTime() + "ms");

        //获取医生和加锁人soid集合
        List<Long> employeeSoids = getDoctorSoidsAndLockUserSoids(docReportServiceLocks, docReportRequisitionRelationVoList);
        //批量查询员工信息
        Map<Long, String> employeeMap = mdmService.findListBySoids(employeeSoids);

        //获取报告锁状态和加锁人名称
         gainReportLockUserNameAndLockStatus(tmpList, docReportServiceLocks, employeeMap);

        //获取报告医生和状态对象map
        Map<String, DocReportRequisitionRelationVo> relationMap = gainReportDoctorAndStatusMap(docReportRequisitionRelationVoList);
        //报告list返回对象中添加报告状态，医生
        list = addParametersToReport(detailCodingSystemService, tmpList, employeeMap, relationMap);

        stopWatch.stop();
        log.info("补充报告状态和书写医生end: " + "==================================================" + "本次耗时:" + stopWatch.getTime() + "ms");
        return list;
    }

  /**
    *
    * 功能描述：获取报告医生和状态对象map
    *
    * @date  2021/8/11
    * @param [ docReportRequisitionRelationVoList]
    * @return java.util.Map<java.lang.String,com.mida.bms.report.vo.DocReportRequisitionRelationVo>
    **/
    private Map<String, DocReportRequisitionRelationVo> gainReportDoctorAndStatusMap(List<DocReportRequisitionRelationVo> docReportRequisitionRelationVoList) {
        Map<String, DocReportRequisitionRelationVo> relationMap = new HashMap<>();
        if (ObjectUtils.isNotEmpty(docReportRequisitionRelationVoList)) {

            //将值集soid为key,值集name为value放入map中
            for (DocReportRequisitionRelationVo vo : docReportRequisitionRelationVoList) {
                //key=申请单标识_登记标识_检查标识
                String key = String.valueOf(vo.getRequestSoid());
//               String key= vo.getRequestSoid()+"_"+vo.getRegistrationFormSoid()+"_"+ vo.getOperatorSoid();
                if (relationMap.get(key) == null) {
                    relationMap.put(key, vo);
                }
            }

        }
        return relationMap;
    }

    @NotNull
    private List<Long> getDoctorSoidsAndLockUserSoids(List<DocReportServiceLock> docReportServiceLocks, List<DocReportRequisitionRelationVo> docReportRequisitionRelationVoList) {
        Map<Long, String> employeeMap = new HashMap<>();
        Set<Long> lockUserSoids = new HashSet<>();
        lockUserSoids = docReportServiceLocks
                .stream()
                .map(DocReportServiceLock::getLockUserSoid)
                .collect(Collectors.toSet());

        //初始化批量查询员工信息查询条件（人员集合）
        Set<Long> firstWriteDoctors = docReportRequisitionRelationVoList
                .stream()
                .map(DocReportRequisitionRelationVo::getFirstWriteDoctor)
                .collect(Collectors.toSet());
        Set<Long> firstTrialDoctors = docReportRequisitionRelationVoList
                .stream()
                .map(DocReportRequisitionRelationVo::getFirstTrialDoctor)
                .collect(Collectors.toSet());
        lockUserSoids.addAll(firstWriteDoctors);
        lockUserSoids.addAll(firstTrialDoctors);
        return lockUserSoids.stream().distinct().collect(Collectors.toList());
    }

    /**
     * 功能描述：获取报告锁状态和加锁人名称
     *
     * @param [ list, docReportServiceLocks, employeeMap]
     * @return void
     * @date 2021/8/11
     **/
    private List<DocReportListVo> gainReportLockUserNameAndLockStatus(List<DocReportListVo> list, List<DocReportServiceLock> docReportServiceLocks, Map<Long, String> employeeMap) {
        Map<String, DocReportServiceLock> LocksMap = new HashMap<>();
        if (ObjectUtils.isNotEmpty(docReportServiceLocks)) {
            for (DocReportServiceLock lock : docReportServiceLocks) {
//                String key = String.valueOf(docReportServiceLock.getRequestSoid());
                String key = lock.getRequestSoid()
                        + "_" + lock.getRegistrationSheetSoid()
                        + "_" + lock.getExamCheckSoid()
                        + "_" + lock.getPolicySoid();
                if (ObjectUtils.isEmpty(LocksMap.get(key))) {
                    LocksMap.put(key, lock);
                }
            }
        }

        Map<Long, String> finalEmployeeMap = employeeMap;
        list.forEach(m -> {
            String key = m.getRequestSoid()
                    + "_" + m.getRegistrationFormSoid()
                    + "_" + m.getOperatorSoid()
                    + "_" + m.getReportType();
            DocReportServiceLock docReportServiceLock = LocksMap.get(key);
            if (ObjectUtils.isNotEmpty(docReportServiceLock)) {
                Long lockUserSoid = docReportServiceLock.getLockUserSoid();
                Long status = docReportServiceLock.getStatus();
                String lockUserName = finalEmployeeMap.get(lockUserSoid);
                m.setLockUserName(lockUserName);
                m.setLockStatus(status);
                m.setLockUserSoid(docReportServiceLock.getLockUserSoid());
            }
        });
        return list;
    }

    /**
     * @return java.util.List<com.mida.bms.report.vo.DocReportRequisitionRelationVo>
     * @Author WXL
     * @Description 批量获取 报告状态，审核，书写医生、审核医生
     * @Date 2021/8/7
     * @Param [list]
     **/
    private List<DocReportRequisitionRelationVo> queryDocReportRequisitionRelationVos(List<DocReportListVo> list) {
        List<ReportSearchRequest> reportSearchRequestList = new ArrayList<>();
        list.forEach(docReportListVo -> {
            //包装查询报告状态，审核，书写医生条件
            ReportSearchRequest reportSearchRequest = new ReportSearchRequest();
            reportSearchRequest.setRequestSoid(docReportListVo.getRequestSoid());//申请单标识
            reportSearchRequest.setRegistrationFormSoid(docReportListVo.getRegistrationFormSoid());//登记标识
            reportSearchRequest.setExaminationVisitSoid(docReportListVo.getOperatorSoid()); //检查标识
            reportSearchRequestList.add(reportSearchRequest);
        });
        ReportSearchVo reportSearchVo = new ReportSearchVo(reportSearchRequestList);
        ListResult<List<DocReportRequisitionRelationVo>> listListResult = docReportServiceApi.selectDoctorAndStatusList(reportSearchVo);
        return listListResult.getData();
    }


}
